import warnings
warnings.filterwarnings('ignore')
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import tensorflow as tf
tf.compat.v1.logging.set_verbosity(40)
import numpy as np
import librosa
import librosa.display
import matplotlib.pyplot as plt
import seaborn as sns
import tensorflow.keras.layers as layers
from sklearn.metrics import confusion_matrix,accuracy_score,f1_score,precision_score,recall_score
from sklearn.model_selection import train_test_split
from tensorflow.keras.losses import binary_crossentropy

def extract_features(path):
    x_data=[]
    y_data=[]
    for i,label_name in enumerate(os.listdir(path)):
        label_path = os.path.join(path,label_name)
        for voice_name in os.listdir(label_path):
            voice_path = os.path.join(label_path, voice_name)

            x,sr=librosa.load(voice_path, res_type='kaiser_fast',sr=None)
            mfccs=np.mean(librosa.feature.mfcc(x,sr=sr,n_mfcc=100).T,axis=0)
            x_data.append(mfccs)
            y_data.append(i)

    return np.array(x_data),np.array(y_data)

x_data,y_data=extract_features(r'E:\DATA\archive\cats_dogs\train')

x_train,x_test,y_train,y_test = train_test_split(x_data,y_data,train_size=0.8)
x_val,x_test,y_val,y_test = train_test_split(x_test,y_test,train_size=0.5)

model=tf.keras.Sequential()
model.add(layers.Dense(input_shape=(100,), units= 200,activation='relu'))
model.add(layers.Dense(200,activation='relu'))
model.add(layers.Dense(200,activation='relu'))
model.add(layers.Dense(1,activation='sigmoid'))

model.summary()

model.compile(optimizer='adam',loss=binary_crossentropy,metrics=['accuracy'])

history=model.fit(x_train,y_train,epochs=10,validation_data=(x_val,y_val))

plt.plot(history.history['loss'],'ro-',label='train')
plt.plot(history.history['val_loss'],'go--',label='val')
plt.legend()
plt.title('loss')
plt.show()

plt.plot(history.history['accuracy'],'ro-',label='train')
plt.plot(history.history['val_accuracy'],'go--',label='val')
plt.legend()
plt.title('accuracy')
plt.show()

y_pred=model.predict(x_test)
y_pred=(y_pred>0.5)*1

accuracy_score_test = accuracy_score(y_test,y_pred)
print(f'准确率:{accuracy_score_test:.3f}')

plt.pie([accuracy_score_test,1-accuracy_score_test],explode=[0,0.02],labels=['true','false'],autopct='%1.1f%%')
plt.show()

confusion_matrix_test = confusion_matrix(y_test,y_pred)
print(f'混淆矩阵:\n{confusion_matrix_test}')

sns.heatmap(confusion_matrix_test,annot=True)
plt.show()

precision_score_test = precision_score(y_test,y_pred)
print(f'查准率:{precision_score_test:.3f}')

recall_score_test = recall_score(y_test,y_pred)
print(f'查全率:{recall_score_test:.3f}')

f1_score_test = f1_score(y_test,y_pred)
print(f'f1精度:{f1_score_test:.3f}')